package com.jc.platform.songjiajia.service.base.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jc.platform.songjiajia.mapper.IPartnerMapper;
import com.jc.platform.songjiajia.mapper.IPurchaseContractMapper;
import com.jc.platform.songjiajia.mapper.IRPartnerPurchaseMapper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;




import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jc.platform.common.annotation.DataIsolation;
import com.jc.platform.common.constants.GlobalConstant;
import com.jc.platform.common.constants.StringPool;
import com.jc.platform.common.model.UserInfo;
import com.jc.platform.common.model.QueryParam;
import com.jc.platform.common.result.PageInfo;
import com.jc.platform.common.result.ResultCodeEnum;
import com.jc.platform.common.result.ResultModel;
import com.jc.platform.common.search.SqlUtils;
import com.jc.platform.common.utils.BeanUtil;
import com.jc.platform.common.utils.RequestUtil;
import com.jc.platform.songjiajia.vo.PurchaseContractVO;
import com.jc.platform.songjiajia.entity.PurchaseContractEntity;
import com.jc.platform.songjiajia.mapper.IPurchaseContractMapper;
import com.jc.platform.songjiajia.service.base.impl.BaseServiceImpl;
import com.jc.platform.songjiajia.service.base.IBasePurchaseContractService;
import com.jc.platform.mybatis.utils.CollectCovertUtil;
import com.jc.platform.mybatis.utils.ConditionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import com.jc.platform.songjiajia.vo.PurchaseContractFileInfoVO;
import com.jc.platform.songjiajia.service.IPurchaseContractFileInfoService;

import com.jc.platform.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.jc.platform.common.utils.CollectionUtil;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import com.jc.platform.songjiajia.mapper.IRPartnerPurchaseMapper;
import com.jc.platform.songjiajia.entity.RPartnerPurchaseEntity;

/**
 * ClassName AbstractPurchaseContractServiceImpl.java
 * Description 采购合同
 *
 * @author 集团管理员
 * @date 2022/01/22
 */
@Slf4j
public abstract class AbstractPurchaseContractServiceImpl extends BaseServiceImpl<PurchaseContractVO> implements IBasePurchaseContractService
{
	private static final String KEY_PREFIX = "db_platformSongjiajia:t_purchaseContract";

    @Autowired
    private RedisUtils<String, PurchaseContractVO> redisUtils;
    @Autowired
    private IPurchaseContractFileInfoService purchaseContractFileInfoService;
    @Autowired
    private IPartnerMapper partnerMapper;
    @Autowired
    private IPurchaseContractMapper purchaseContractMapper;
    @Autowired
    private IRPartnerPurchaseMapper rPartnerPurchaseMapper;






	@Override
	public ResultModel<PurchaseContractVO> insert(PurchaseContractVO purchaseContractVO)
	{
		PurchaseContractEntity entity = new PurchaseContractEntity();
		entity.copyFormVO(purchaseContractVO);
		purchaseContractMapper.insert(entity);
        List <Long> purchaseContractList = purchaseContractVO.getPartnerList();
        if(CollectionUtil.isNotEmpty(purchaseContractList)){
            purchaseContractList.forEach(mtmId -> {
                RPartnerPurchaseEntity mtmEntity = new RPartnerPurchaseEntity();
                mtmEntity.setContractId(entity.getId());
                mtmEntity.setPartnerId(mtmId);
                rPartnerPurchaseMapper.insert(mtmEntity);
            });
        }

            PurchaseContractFileInfoVO purchaseContractFileInfo = purchaseContractVO.getPurchaseContractFileInfo();
            if (purchaseContractFileInfo != null) {
               purchaseContractFileInfo.setPurchaseContractId(entity.getId());
                purchaseContractFileInfoService.insert(purchaseContractFileInfo);
            }
		purchaseContractVO.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
		return ResultModel.success(purchaseContractVO);
	}

	@Override
	public ResultModel<PurchaseContractVO> update(PurchaseContractVO purchaseContract)
	{
		PurchaseContractEntity entity = new PurchaseContractEntity();
		entity.copyFormVO(purchaseContract);
		purchaseContractMapper.updateById(entity);

        rPartnerPurchaseMapper.deleteByContractId(purchaseContract.getId());
        List <Long> purchaseContractList = purchaseContract.getPartnerList();
        if(CollectionUtil.isNotEmpty(purchaseContractList)){
            purchaseContractList.forEach(mtmId -> {
                RPartnerPurchaseEntity mtmEntity = new RPartnerPurchaseEntity();
                mtmEntity.setContractId(purchaseContract.getId());
                mtmEntity.setPartnerId(mtmId);
                rPartnerPurchaseMapper.insert(mtmEntity);
            });
        }

        PurchaseContractFileInfoVO purchaseContractFileInfo = purchaseContract.getPurchaseContractFileInfo();
            if (purchaseContractFileInfo != null) {
         PurchaseContractFileInfoVO sourcePurchaseContractId = purchaseContractFileInfoService.getByPurchaseContractIdExtend(entity.getId());
         purchaseContractFileInfo.setPurchaseContractId(entity.getId());
        if (sourcePurchaseContractId != null) {
            purchaseContractFileInfo.setId(sourcePurchaseContractId.getId());
            purchaseContractFileInfoService.update(purchaseContractFileInfo);
        } else {
            purchaseContractFileInfoService.insert(purchaseContractFileInfo);
        }
            }

		purchaseContract.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
        delFromRedisAsync(entity.getId());
		entity = purchaseContractMapper.selectById(entity.getId());
		return ResultModel.success(entity.copyToVO());
	}


    @Override
	public ResultModel<Boolean> delete(Long id)
	{
                        purchaseContractFileInfoService.delByPurchaseContractId(id);
        
         int count = purchaseContractMapper.deleteById(id);

        rPartnerPurchaseMapper.deleteByContractId(id);
		if (count > 0)
		{
			delRedisKeyBatch(KEY_PREFIX);
            delFromRedisAsync(id);
			return ResultModel.success(true);
		}
		else
		{
			return ResultModel.success(false);
		}
	}

    @Override
	public ResultModel<Boolean> deleteBatch(List<Long> ids)
	{
        if (CollectionUtil.isEmpty(ids)) {
			return ResultModel.success(true);
		}

        ids.forEach(x -> {
            purchaseContractFileInfoService.delByPurchaseContractId(x);
        });              
        ids.forEach(id -> {
            purchaseContractMapper.deleteById(id);
        });

        delRedisKeyBatch(KEY_PREFIX);
        return ResultModel.success(true);
	}




	@Override
	public Boolean checkNotExists(Long id, String property, String value)
	{
        QueryWrapper<PurchaseContractEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(BeanUtil.newInstance(PurchaseContractEntity.class));
        queryWrapper.eq(SqlUtils.getColumnByProperty(property), value);

        if(id!=null && id>0){
            queryWrapper.ne(StringPool.ID, id);
        }


        return purchaseContractMapper.selectCount(queryWrapper) <= 0;
	}

	@Override
	public ResultModel<PurchaseContractVO> get(Long id)
	{
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, id);
        PurchaseContractVO purchaseContractVO = getRedis(redisKey);
        if (purchaseContractVO == null)
        {
            PurchaseContractEntity entity = purchaseContractMapper.selectById(id);
            if (entity == null){
                return ResultModel.failed();
            }
            purchaseContractVO = entity.copyToVO();

            purchaseContractVO.setPartnerPOList(CollectCovertUtil.listVO(partnerMapper.findByPurchaseContract(id)));
            purchaseContractVO.setPurchaseContractFileInfo(purchaseContractFileInfoService.getByPurchaseContractIdExtend(purchaseContractVO.getId()));


                        purchaseContractVO.setPartnerList(rPartnerPurchaseMapper.findPartnerIdByContractId(entity.getId()));

            setRedis(redisKey, purchaseContractVO);
        }
        return ResultModel.success(purchaseContractVO);
	}

	@Override
	@DataIsolation(value = {"group_id","org_id","dept_id","create_id"})
	public ResultModel<List<PurchaseContractVO>> find(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:find." + queryParam.toString());
        List<PurchaseContractVO> list = getRedisForList(redisKey);
            if (list == null || list.isEmpty())
            {
                if (queryParam.getQuery().get("group_id") != null) {
                    queryParam.getQuery().put("purchase_contract.group_id", queryParam.getQuery().get("group_id"));
                    queryParam.getQuery().remove("group_id");
                }
                if (queryParam.getQuery().get("org_id") != null) {
                    queryParam.getQuery().put("purchase_contract.org_id", queryParam.getQuery().get("org_id"));
                    queryParam.getQuery().remove("org_id");
                }
                if (queryParam.getQuery().get("dept_id") != null) {
                    queryParam.getQuery().put("purchase_contract.dept_id", queryParam.getQuery().get("dept_id"));
                    queryParam.getQuery().remove("dept_id");
                }
                QueryWrapper<PurchaseContractVO> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PurchaseContractVO.class);
                list = purchaseContractMapper.findExtend(queryWrapper);

                if (list != null && !list.isEmpty())
                {
                    if(CollectionUtil.isNotEmpty(list)){
                        list.stream().map(item -> {
                            item.setPartnerList(rPartnerPurchaseMapper.findPartnerIdByContractId(item.getId()));
                            return item;
                        })
                        .collect(Collectors.toList());
                    }
                    setRedis(redisKey,list);
                }
            }
        return ResultModel.success(list);
	}

	@Override
	@DataIsolation(value = {"group_id","org_id","dept_id","create_id"})
	public ResultModel<PageInfo<PurchaseContractVO>> finds(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());

        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:finds." + queryParam.toString());
        PageInfo<PurchaseContractVO> page = getRedisForPage(redisKey);
        if (page == null)
        {
            if (queryParam.getQuery().get("group_id") != null) {
                queryParam.getQuery().put("purchase_contract.group_id", queryParam.getQuery().get("group_id"));
                queryParam.getQuery().remove("group_id");
            }
            if (queryParam.getQuery().get("org_id") != null) {
                queryParam.getQuery().put("purchase_contract.org_id", queryParam.getQuery().get("org_id"));
                queryParam.getQuery().remove("org_id");
            }
            if (queryParam.getQuery().get("dept_id") != null) {
                queryParam.getQuery().put("purchase_contract.dept_id", queryParam.getQuery().get("dept_id"));
                queryParam.getQuery().remove("dept_id");
            }
            QueryWrapper<PurchaseContractVO> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PurchaseContractVO.class);
            IPage<PurchaseContractVO> iPage = purchaseContractMapper.findExtends(ConditionUtil.getPage(queryParam), queryWrapper);
            page = new PageInfo<>();
            page.setList(iPage.getRecords());
            page.setPageNum(queryParam.getPageNum());
            page.setPageSize(queryParam.getPageSize());
            page.setTotal(iPage.getTotal());
            if(CollectionUtil.isNotEmpty(page.getList())){
                page.getList().stream().map(item -> {
                    item.setPartnerList(rPartnerPurchaseMapper.findPartnerIdByContractId(item.getId()));
                    return item;
                })
                .collect(Collectors.toList());
            }
            setRedis(redisKey,page);
        }
        return ResultModel.success(page);

	}

    @Override
	public ResultModel<Integer> count(QueryParam queryParam)
	{
        QueryWrapper<PurchaseContractEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PurchaseContractEntity.class);
        Integer count = purchaseContractMapper.selectCount(queryWrapper);
		return ResultModel.success(count);
	}



    /**
     * 执行【合作单位】添加
     *
     * @param id
     * @param partnerId
     * @return
     */
    private int doAddPartner(Long id, Long... partnerId) {
        int count = 0;
        for (Long _id : partnerId) {
            if(partnerMapper.selectById(_id) != null){
                count += purchaseContractMapper.addPartner(id, _id);
            }
        }
        return count;
    }

    /**
     * 设置【合作单位】
     *
     * @param id
     * @param partnerId
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public int setPartner(Long id, Long[] partnerId) {
        purchaseContractMapper.removeAllPartner(id);
        delFromRedisAsync(id);
        if(ArrayUtils.isEmpty(partnerId)){
            return 0;
        }
        return doAddPartner(id, partnerId);
    }





    private void delFromRedisAsync(Object id)
	{
        redisUtils.del(RedisUtils.getRedisKey(KEY_PREFIX, id));
	}

	private void delColRedis()
	{
		String keyPattern = RedisUtils.getRedisKey(KEY_PREFIX, "collection:*");
		Set<String> keys = redisUtils.keys(keyPattern);
		if (keys != null)
		{
			String[] keyArray = keys.toArray(new String[] {});
			redisUtils.del(keyArray);
		}
	}
}

